package cn.lili.modules.order.aftersale.serviceimpl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.ObjectFieldEnum;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.BeanUtil;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.common.utils.SnowFlake;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import cn.lili.exchange.AmqpExchangeProperties;
import cn.lili.lililogs.logs.annotation.SystemLogPoint;
import cn.lili.modules.goods.client.GoodsClient;
import cn.lili.modules.goods.client.GoodsSkuClient;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.vos.yunxin.AppAfterSalesCreate;
import cn.lili.modules.member.client.UserAddressClient;
import cn.lili.modules.member.client.UserClient;
import cn.lili.modules.member.entity.dos.User;
import cn.lili.modules.member.entity.dos.UserAddress;
import cn.lili.modules.member.entity.dto.AddressSearchParams;
import cn.lili.modules.member.entity.enums.AddressTypeEnum;
import cn.lili.modules.order.aftersale.aop.AfterSaleLogPoint;
import cn.lili.modules.order.aftersale.entity.dos.AfterSale;
import cn.lili.modules.order.aftersale.entity.dto.AfterSaleDTO;
import cn.lili.modules.order.aftersale.entity.vo.AfterSaleApplyVO;
import cn.lili.modules.order.aftersale.entity.vo.AfterSaleSearchParams;
import cn.lili.modules.order.aftersale.entity.vo.AfterSaleVO;
import cn.lili.modules.order.aftersale.mapper.AfterSaleMapper;
import cn.lili.modules.order.aftersale.service.AfterSaleService;
import cn.lili.modules.order.order.entity.dos.*;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.order.order.entity.enums.*;
import cn.lili.modules.order.order.service.OrderFlowService;
import cn.lili.modules.order.order.service.OrderItemService;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.order.order.service.RefundFlowService;
import cn.lili.modules.order.trade.entity.enums.AfterSaleRefundWayEnum;
import cn.lili.modules.order.trade.entity.enums.AfterSaleStatusEnum;
import cn.lili.modules.order.trade.entity.enums.AfterSaleTypeEnum;
import cn.lili.modules.payment.entity.enums.PaymentMethodEnum;
import cn.lili.modules.promotion.client.GreenClient;
import cn.lili.modules.promotion.client.ReturnActivityClient;
import cn.lili.modules.promotion.client.ReturnActivityGoodsClient;
import cn.lili.modules.promotion.client.TicketOrderClient;
import cn.lili.modules.promotion.entity.enums.TicketOrderStatusEnum;
import cn.lili.modules.promotion.entity.enums.GreenAmountInfoStatusEnum;
import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam;
import cn.lili.modules.statistics.util.StatisticsDateUtil;
import cn.lili.modules.store.client.StoreClient;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.modules.system.client.LogisticsClient;
import cn.lili.modules.system.entity.dos.Logistics;
import cn.lili.modules.system.entity.vo.Traces;
import cn.lili.mybatis.util.PageUtil;
import cn.lili.mybatis.util.SceneHelp;
import cn.lili.routing.AfterSaleRoutingKey;
import cn.lili.util.AmqpMessage;
import cn.lili.util.AmqpSender;
import com.alibaba.fastjson.JSONObject;
import com.api.PayApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.transaction.annotation.ShardingTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 售后业务层实现
 *
 * @author Chopper
 * @since 2020/11/17 7:38 下午
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AfterSaleServiceImpl extends ServiceImpl<AfterSaleMapper, AfterSale> implements AfterSaleService {

    /**
     * 订单
     */
    private final OrderService orderService;

    /**
     * 退款流水
     */
    private final RefundFlowService refundFlowService;
    /**
     * 订单货物
     */
    private final OrderItemService orderItemService;
    /**
     * 物流公司
     */
    private final LogisticsClient logisticsClient;
    /**
     * RocketMQ配置
     */
    private final AmqpSender amqpSender;

    private final AmqpExchangeProperties amqpExchangeProperties;

    private final UserAddressClient addressClient;

    private final StoreClient storeClient;

    private final PayApi payApi;

    private final UserClient userClient;

    private final ReturnActivityGoodsClient returnActivityGoodsClient;

    private final ReturnActivityClient returnActivityClient;

    private final TicketOrderClient ticketOrderClient;

    private final GoodsClient goodsClient;

    private final GreenClient greenClient;

    private final OrderFlowService orderFlowService;

    @Override
    public Page<AfterSaleVO> getAfterSalePages(AfterSaleSearchParams saleSearchParams) {
        QueryWrapper<AfterSaleVO> queryWrapper = saleSearchParams.queryWrapper();
        if (SceneEnums.URBAN_SUBSTATION.equals(Objects.requireNonNull(UserContext.getCurrentUser()).getScene())) {
            List<Store> storeList = storeClient.getSupplierListByUrbanId(UserContext.getCurrentUser().getId());
            if (!storeList.isEmpty()) {
                List<String> supplierIds = storeList.stream().map(Store::getId).toList();
                queryWrapper.in("supplier_id", supplierIds);
            }
        }
        return baseMapper.queryByParams(PageUtil.initPage(saleSearchParams), queryWrapper);
    }

    @Override
    public List<AfterSale> exportAfterSaleOrder(AfterSaleSearchParams saleSearchParams) {
        return this.list(saleSearchParams.queryWrapper());
    }

    @Override
    public AfterSaleVO getAfterSale(String sn) {
        return this.baseMapper.getAfterSaleVO(sn);
    }

    @Override
    public AfterSaleApplyVO getAfterSaleVO(String sn) {

        AfterSaleApplyVO afterSaleApplyVO = new AfterSaleApplyVO();

        //获取订单货物判断是否可申请售后
        OrderItem orderItem = orderItemService.getBySn(sn);

        //未申请售后订单货物或部分售后才能进行申请
        if (!orderItem.getAfterSaleStatus().equals(OrderItemAfterSaleStatusEnum.NOT_APPLIED.name()) && !orderItem.getAfterSaleStatus().equals(OrderItemAfterSaleStatusEnum.PART_AFTER_SALE.name())) {
            throw new ServiceException(ResultCode.AFTER_SALES_BAN);
        }

        //获取售后类型
        Order order = orderService.getBySn(orderItem.getOrderSn());

        //订单未支付，不能申请申请售后
        if (order.getPaymentMethod() == null) {
            throw new ServiceException(ResultCode.AFTER_SALES_NOT_PAY_ERROR);
        }
        //判断支付方式是否为线上支付
        if (order.getPaymentMethod().equals(PaymentMethodEnum.BANK_TRANSFER.name())) {
            afterSaleApplyVO.setRefundWay(AfterSaleRefundWayEnum.OFFLINE.name());
        } else {
            afterSaleApplyVO.setRefundWay(AfterSaleRefundWayEnum.ORIGINAL.name());
        }
        //判断订单类型，虚拟订单只支持退款
        if (order.getOrderType().equals(OrderTypeEnum.VIRTUAL.name())) {
            afterSaleApplyVO.setReturnMoney(true);
            afterSaleApplyVO.setReturnGoods(false);
        } else {
            afterSaleApplyVO.setReturnMoney(true);
            afterSaleApplyVO.setReturnGoods(true);
        }

        PriceDetailDTO priceDetailDTO = orderItem.getPriceDetailDTO();
        afterSaleApplyVO.setAccountType(order.getPaymentMethod());
//        afterSaleApplyVO.setApplyRefundPrice(CurrencyUtil.div(CurrencyUtil.sub(priceDetailDTO.getFlowPrice(), priceDetailDTO.getFreightPrice()), orderItem.getNum()));
        //增加 priceDetailDTO.getFlowPrice() 判断
        afterSaleApplyVO.setApplyRefundPrice(CurrencyUtil.div(CurrencyUtil.sub((priceDetailDTO.getFlowPrice() <= 0 ? orderItem.getFlowPrice() : priceDetailDTO.getFlowPrice()), priceDetailDTO.getFreightPrice()), orderItem.getNum()));
        afterSaleApplyVO.setNum(orderItem.getNum());
        afterSaleApplyVO.setGoodsId(orderItem.getGoodsId());
        afterSaleApplyVO.setGoodsName(orderItem.getGoodsName());
        afterSaleApplyVO.setImage(orderItem.getImage());
        afterSaleApplyVO.setGoodsPrice(orderItem.getGoodsPrice());
        afterSaleApplyVO.setSkuId(orderItem.getSkuId());
        afterSaleApplyVO.setMemberId(order.getBuyerId());
        return afterSaleApplyVO;
    }

    @Override
    @AfterSaleLogPoint(sn = "#rvt.sn", description = "'售后申请:售后编号['+#rvt.sn+']'")
    @SystemLogPoint(description = "售后-售后申请", customerLog = "'售后申请:售后编号['+#rvt.sn+']'")
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public AfterSale saveAfterSale(AfterSaleDTO afterSaleDTO) {

        OrderItem orderItem = orderItemService.getBySn(afterSaleDTO.getOrderItemSn());

        PriceDetailDTO priceDetailDTO = orderItem.getPriceDetailDTO();
        //重写退款金额 = 流水 / 数量 * 申请数量
        //增加判断取值 priceDetailDTO.getFlowPrice() > 0 ? priceDetailDTO.getFlowPrice() : orderItem.getFlowPrice()
        log.info("#saveAfterSale# priceDetailDTO.getFlowPrice():{},orderItem.getFlowPrice():{}", priceDetailDTO.getFlowPrice(), orderItem.getFlowPrice());
//        afterSaleDTO.setApplyRefundPrice(CurrencyUtil.mul(
//                CurrencyUtil.div(CurrencyUtil.sub(priceDetailDTO.getFlowPrice(), priceDetailDTO.getFreightPrice()), orderItem.getNum())
//                , afterSaleDTO.getNum()));
        afterSaleDTO.setApplyRefundPrice(CurrencyUtil.mul(
                CurrencyUtil.div(CurrencyUtil.sub((priceDetailDTO.getFlowPrice() > 0 ? priceDetailDTO.getFlowPrice() : orderItem.getFlowPrice()), priceDetailDTO.getFreightPrice()), orderItem.getNum())
                , afterSaleDTO.getNum()));

        //检查当前订单是否可申请售后
        this.checkAfterSaleType(afterSaleDTO);

        //添加售后
        return addAfterSale(afterSaleDTO);
    }

    @AfterSaleLogPoint(sn = "#afterSaleSn", description = "'审核售后:售后编号['+#afterSaleSn+']，'+ #serviceStatus")
    @SystemLogPoint(description = "售后-审核售后", customerLog = "'审核售后:售后编号['+#afterSaleSn+']，'+ #serviceStatus")
    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public AfterSale review(String afterSaleSn, String serviceStatus, Double actualRefundPrice, String remark) {
        //根据售后单号获取售后单
        AfterSale afterSale = this.getBySn(afterSaleSn);

        //判断为待审核的售后服务
        if (!afterSale.getServiceStatus().equals(AfterSaleStatusEnum.APPLY.name())) {
            throw new ServiceException(ResultCode.AFTER_SALES_DOUBLE_ERROR);
        }
        if (actualRefundPrice != null && actualRefundPrice > afterSale.getApplyRefundPrice()) {
            throw new ServiceException("退款金额不可大于实际付款金额");
        }
        if (actualRefundPrice == 0) {
            throw new ServiceException("退款金额不可为0");
        }
        //强制退款金额=售后申请金额
        afterSale.setActualRefundPrice(actualRefundPrice != null ? actualRefundPrice : afterSale.getApplyRefundPrice());

        //判断审核状态
        //如果售后类型为：退款，审核状态为已通过并且退款方式为原路退回，售后单状态为已完成。
        //如果售后类型为：退款，审核状态已通过并且退款方式为线下退回，售后单状态为待退款。
        //如果售后类型不为退款，售后单状态为：已通过。
        AfterSaleStatusEnum afterSaleStatusEnum;
        //审核通过判定
        if (serviceStatus.equals(AfterSaleStatusEnum.PASS.name())) {
            //如果为退款操作
            if (afterSale.getServiceType().equals(AfterSaleTypeEnum.RETURN_MONEY.name()) && afterSale.getRefundWay().equals(AfterSaleRefundWayEnum.ORIGINAL.name())) {
                //调用退款
                log.info("xq--------afterSale---" + JSONObject.toJSONString(afterSale));
                paymentRefund(afterSale);

                if (afterSale.getReturnFmoney() > 0) {
                    User user = userClient.getById(afterSale.getMemberId());
                    if (CharSequenceUtil.isEmpty(user.getOpenId())) {
                        throw new ServiceException(ResultCode.AFTER_SALES_RETURN_FMONEY_ERROR);
                    }
                    // 退F分抵扣
//                    boolean orderReturn = payApi.payment(user.getOpenId(),"积分退回", (int) (afterSale.getReturnFmoney() * 100),2, 3);
//                    if (!orderReturn) {
//                        throw new ServiceException(ResultCode.AFTER_SALES_RETURN_FMONEY_BY_FYPAY_ERROR);
//                    }
                }
                //修改售后单状态为已完成
                afterSale.setRefundTime(new Date());
                afterSaleStatusEnum = AfterSaleStatusEnum.COMPLETE;

                // 更新门票订单状态
                Goods goods = goodsClient.getById(afterSale.getGoodsId());
                if (null != goods && null != goods.getIsTicket() && goods.getIsTicket()) {
                    OrderItem orderItem =
                            orderItemService.getOne(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn, afterSale.getOrderSn()).eq(OrderItem::getSkuId, afterSale.getSkuId()));
                    ticketOrderClient.updateOrderStatus(orderItem.getOrderSn(), TicketOrderStatusEnum.REFUND.name());
                }

                updateUserReturnActivity(afterSale);
            }
            // 如果退货操作 && 线下支付 则售后单状态为待退款
            else if (afterSale.getServiceType().equals(AfterSaleTypeEnum.RETURN_MONEY.name())) {
                afterSaleStatusEnum = AfterSaleStatusEnum.WAIT_REFUND;
            }
            //否则为退货操作 审核通过，则标记为申请通过，由买家继续执行
            else {
                afterSaleStatusEnum = AfterSaleStatusEnum.PASS;
            }
            //将订单结算状态，变更为，已售后
            LambdaUpdateWrapper<OrderFlow> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(OrderFlow::getProfitSharing, ProfitSharingStatusEnum.AFTER_SALE.name());
            updateWrapper.eq(OrderFlow::getOrderSn, afterSale.getOrderSn());
            if (orderFlowService.update(updateWrapper)) {
                //已揽件状态下的订单, 这里增加更改主订单的状态为已取消
                Order orderResult = orderService.getBySn(afterSale.getOrderSn());
                Double applyRefundPriceTotal = baseMapper.sumPassOrdersPrice(afterSale.getOrderSn(), AfterSaleStatusEnum.COMPLETE.name());
                //所有订单都已退款,则更改主订单状态
                if (orderResult != null && orderResult.getOrderStatus().equals(OrderStatusEnum.OVERVIEW.name()) && applyRefundPriceTotal != null && (afterSale.getApplyRefundPrice() + applyRefundPriceTotal >= orderResult.getFlowPrice())) {
                    LambdaUpdateWrapper<Order> updateWrOrder = new LambdaUpdateWrapper<>();
                    updateWrOrder.eq(true, Order::getSn, afterSale.getOrderSn());
                    updateWrOrder.set(true, Order::getOrderStatus, OrderStatusEnum.CANCELLED.name());
                    orderService.update(updateWrOrder);
                }
            }
        } else {
            afterSaleStatusEnum = AfterSaleStatusEnum.REFUSE;
        }

        afterSale.setServiceStatus(afterSaleStatusEnum.name());
        afterSale.setAuditRemark(remark);

        //根据售后编号修改售后单
        this.updateAfterSale(afterSaleSn, afterSale);
        //根据售后状态。修改OrderItem订单中正在售后商品数量及状态
        this.updateOrderItemAfterSaleStatus(afterSale);
        //发送售后消息
        this.sendAfterSaleMessage(afterSale);

        //取消贡献值
        greenClient.settleDirect(afterSale.getOrderSn(),null, GreenAmountInfoStatusEnum.CANCELLED.name());
        return afterSale;
    }

    private void updateUserReturnActivity(AfterSale afterSale) {
        // 更新用户全返卷
        // 判断售后商品是否是全返商品
        if (returnActivityGoodsClient.isReturnActivityGoods(afterSale.getGoodsId())) {
            // 重新计算用户全返卷
            OrderItem orderItem = orderItemService.getBySn(afterSale.getOrderItemSn());

            Double returnPrice = CurrencyUtil.mul(orderItem.getGoodsPrice(), orderItem.getReturnNum());
            Double price = CurrencyUtil.sub(orderItem.getFlowPrice(), returnPrice);
            orderItem.setFlowPrice(price);

            //Double newFlowPrice = CurrencyUtil.sub(orderItem.getFlowPrice(), afterSale.getActualRefundPrice());

            if (orderItem.getFlowPrice() <= 0) {
                returnActivityClient.deleteUserReturnActivity(afterSale.getMemberId(), afterSale.getOrderItemSn());
            }else {
                // 先删除，再重新计算全返券
                if (returnActivityClient.deleteUserReturnActivity(afterSale.getMemberId(), afterSale.getOrderItemSn())) {
                    returnActivityClient.generate(afterSale.getMemberId(), orderItem);
                }
            }
        }
    }

    @AfterSaleLogPoint(sn = "#afterSaleSn", description = "'买家退货,物流填写:单号['+#afterSaleSn+']，物流单号为['+#logisticsNo+']'")
    @SystemLogPoint(description = "售后-买家退货,物流填写", customerLog = "'买家退货,物流填写:单号['+#afterSaleSn+']，物流单号为['+#logisticsNo+']'")
    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public AfterSale buyerDelivery(String afterSaleSn, String logisticsNo, String logisticsId, String mDeliverTime) {

        if (null == mDeliverTime) {
            throw new ServiceException(ResultCode.AFTER_SALES_DELIVER_TIME_ERROR);
        }

        Date deliverTime = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            deliverTime = sdf.parse(mDeliverTime);
        }catch (Exception e) {
            throw new ServiceException(ResultCode.AFTER_SALES_DELIVER_TIME_ERROR);
        }

        //根据售后单号获取售后单
        AfterSale afterSale = this.getBySn(afterSaleSn);

        //判断为已审核通过，待邮寄的售后服务
        if (!afterSale.getServiceStatus().equals(AfterSaleStatusEnum.PASS.name())) {
            throw new ServiceException(ResultCode.AFTER_STATUS_ERROR);
        }

        //查询会员回寄的物流公司信息
        Logistics logistics = logisticsClient.getById(logisticsId);

        //判断物流公司是否为空
        if (logistics == null) {
            throw new ServiceException(ResultCode.AFTER_STATUS_ERROR);
        }

        afterSale.setMLogisticsCode(logistics.getId());
        afterSale.setMLogisticsName(logistics.getName());
        afterSale.setMLogisticsNo(logisticsNo);
        afterSale.setMDeliverTime(deliverTime);
        //修改售后单状态
        afterSale.setServiceStatus(AfterSaleStatusEnum.BUYER_RETURN.name());

        //根据售后编号修改售后单
        this.updateAfterSale(afterSaleSn, afterSale);

        //供应链售后发货
        OrderItem orderItem = orderItemService.getBySn(afterSale.getOrderItemSn());
        log.info("order 为空 == {}", afterSale.getOrderSn());
        if (orderItem != null) {
            JSONObject jsonObject = orderService.afterSalesSend(orderItem, logistics.getName(), logistics.getCode(), logisticsNo);
            log.info("供应链售后发货 == {}" , jsonObject.toJSONString());
        }
        return afterSale;
    }

    @Override
    public Traces deliveryTraces(String afterSaleSn) {

        //根据售后单号获取售后单
        AfterSale afterSale = this.getBySn(afterSaleSn);
        return logisticsClient.getLogistic(afterSale.getMLogisticsCode(), afterSale.getMLogisticsNo(), afterSale.getMLogisticsNo());
    }

    @Override
    @AfterSaleLogPoint(sn = "#afterSaleSn", description = "#serviceStatus.equals('PASS')?" +
            "'售后-商家收货:单号['+#afterSaleSn+'],处理结果[商家收货]':'售后-商家收货:单号['+#afterSaleSn+'],处理结果[商家拒收],原因['+#remark+']'")
    @SystemLogPoint(description = "售后-商家收货", customerLog = "#serviceStatus.equals('PASS')?" +
            "'售后-商家收货:单号['+#afterSaleSn+'],处理结果[商家收货]':'售后-商家收货:单号['+#afterSaleSn+'],处理结果[商家拒收],原因['+#remark+']'")
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public AfterSale storeConfirm(String afterSaleSn, String serviceStatus, String remark) {
        //根据售后单号获取售后单
        AfterSale afterSale = this.getBySn(afterSaleSn);
        SceneHelp.objectAuthentication(afterSale, ObjectFieldEnum.STORE_ID, ObjectFieldEnum.SUPPLIER_ID);

        //判断是否为已邮寄售后单
        if (!afterSale.getServiceStatus().equals(AfterSaleStatusEnum.BUYER_RETURN.name())) {
            throw new ServiceException(ResultCode.AFTER_STATUS_ERROR);
        }
        AfterSaleStatusEnum afterSaleStatusEnum;
        //判断审核状态
        //在线支付 则直接进行退款
        if (AfterSaleStatusEnum.PASS.name().equals(serviceStatus) && afterSale.getRefundWay().equals(AfterSaleRefundWayEnum.ORIGINAL.name())) {
            //调用退款
            paymentRefund(afterSale);

            // 更新门票订单状态
            Goods goods = goodsClient.getById(afterSale.getGoodsId());
            if (null != goods && null != goods.getIsTicket() && goods.getIsTicket()) {
                OrderItem orderItem =
                        orderItemService.getOne(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn, afterSale.getOrderSn()).eq(OrderItem::getSkuId, afterSale.getSkuId()));
                ticketOrderClient.updateOrderStatus(orderItem.getOrderSn(), TicketOrderStatusEnum.REFUND.name());
            }


            // 更新用户全返券
            updateUserReturnActivity(afterSale);

            afterSaleStatusEnum = AfterSaleStatusEnum.COMPLETE;
        } else if (AfterSaleStatusEnum.PASS.name().equals(serviceStatus)) {
            afterSaleStatusEnum = AfterSaleStatusEnum.WAIT_REFUND;
        } else {
            afterSaleStatusEnum = AfterSaleStatusEnum.SELLER_TERMINATION;
        }
        afterSale.setServiceStatus(afterSaleStatusEnum.name());
        afterSale.setAuditRemark(remark);

        //根据售后编号修改售后单
        this.updateAfterSale(afterSaleSn, afterSale);
        //根据售后状态。修改OrderItem订单中正在售后商品数量及状态
        this.updateOrderItemAfterSaleStatus(afterSale);
        //发送售后消息
        this.sendAfterSaleMessage(afterSale);
        return afterSale;
    }

    @Override
    @AfterSaleLogPoint(sn = "#afterSaleSn", description = "'售后-平台退款:单号['+#afterSaleSn+']，备注为['+#remark+']'")
    @SystemLogPoint(description = "售后-手动团平台退款", customerLog = "'售后-平台退款:单号['+#afterSaleSn+']，备注为['+#remark+']'")
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public AfterSale refund(String afterSaleSn, String remark) {
        //根据售后单号获取售后单
        AfterSale afterSale = this.getBySn(afterSaleSn);
        afterSale.setServiceStatus(AfterSaleStatusEnum.COMPLETE.name());

        //根据售后编号修改售后单
        this.updateAfterSale(afterSaleSn, afterSale);

        // 更新门票订单状态
        Goods goods = goodsClient.getById(afterSale.getGoodsId());
        if (null != goods && null != goods.getIsTicket() && goods.getIsTicket()) {
            OrderItem orderItem =
                    orderItemService.getOne(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn, afterSale.getOrderSn()).eq(OrderItem::getSkuId, afterSale.getSkuId()));
            ticketOrderClient.updateOrderStatus(orderItem.getOrderSn(), TicketOrderStatusEnum.REFUND.name());
        }


        // 更新用户全返券
        updateUserReturnActivity(afterSale);

        //平台退款
        paymentRefund(afterSale);
        //发送退款消息
        this.sendAfterSaleMessage(afterSale);
        return afterSale;
    }


    /**
     * 调用退款
     *
     * @param afterSale 售后
     */
    private void paymentRefund(AfterSale afterSale) {
        OrderItem orderItem = orderItemService.getBySn(afterSale.getOrderItemSn());
        log.info("xq-orderItem" + JSONObject.toJSONString(orderItem));
        Order order = orderService.getBySn(afterSale.getOrderSn());
        log.info("xq-order" + JSONObject.toJSONString(orderItem));
        //根据售后状态。修改OrderItem订单中正在售后商品数量及状态
        refundFlowService.generatorRefundFlow(afterSale, orderItem, order);
    }

    @Override
    @AfterSaleLogPoint(sn = "#afterSaleSn", description = "'售后-买家确认解决:单号['+#afterSaleSn+']'")
    @SystemLogPoint(description = "售后-买家确认解决", customerLog = "'售后-买家确认解决:单号['+#afterSaleSn+']'")
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public AfterSale complete(String afterSaleSn) {
        AfterSale afterSale = this.getBySn(afterSaleSn);
        afterSale.setServiceStatus(AfterSaleStatusEnum.COMPLETE.name());
        this.updateAfterSale(afterSaleSn, afterSale);
        return afterSale;
    }

    @Override
    @AfterSaleLogPoint(sn = "#afterSaleSn", description = "'售后-买家取消:单号['+#afterSaleSn+']'")
    @SystemLogPoint(description = "售后-取消售后", customerLog = "'售后-买家取消:单号['+#afterSaleSn+']'")
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public AfterSale cancel(String afterSaleSn) {

        //根据售后单号获取售后单
        AfterSale afterSale = this.getBySn(afterSaleSn);

        //判断售后单是否可以申请售后
        //如果售后状态为：待审核、已通过则可进行申请售后
        if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.APPLY.name()) || afterSale.getServiceStatus().equals(AfterSaleStatusEnum.PASS.name())) {

            afterSale.setServiceStatus(AfterSaleStatusEnum.BUYER_CANCEL.name());

            //根据售后编号修改售后单
            this.updateAfterSale(afterSaleSn, afterSale);
            //根据售后状态。修改OrderItem订单中正在售后商品数量及状态
            this.updateOrderItemAfterSaleStatus(afterSale);

            //供应链取消售后
            OrderItem orderItem = orderItemService.getBySn(afterSale.getOrderItemSn());
            orderService.afterSalesClose(orderItem);

            return afterSale;
        }
        throw new ServiceException(ResultCode.AFTER_SALES_CANCEL_ERROR);
    }

    @Override
    public long applyNum(String serviceType) {
        AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());
        LambdaQueryWrapper<AfterSale> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AfterSale::getServiceStatus, AfterSaleStatusEnum.APPLY.name());
        queryWrapper.eq(CharSequenceUtil.isNotEmpty(serviceType), AfterSale::getServiceType, serviceType);
        queryWrapper.eq(CharSequenceUtil.equals(authUser.getScene().name(), SceneEnums.STORE.name()), AfterSale::getStoreId, authUser.getExtendId());
        return this.count(queryWrapper);
    }

    @Override
    public UserAddress getStoreAfterSaleAddressDTO(String sn) {
        AfterSale afterSale = this.getBySn(sn);
        AddressSearchParams addressSearchParams = new AddressSearchParams();
        addressSearchParams.setExtendId(afterSale.getStoreId());
        addressSearchParams.setScene(SceneEnums.STORE);
        addressSearchParams.setType(AddressTypeEnum.RECEIVE);
        return addressClient.getByParams(addressSearchParams);
    }

    @Override
    public Page<AfterSale> getStatistics(StatisticsQueryParam statisticsQueryParam, PageVO pageVO) {

        LambdaQueryWrapper<AfterSale> queryWrapper = new LambdaQueryWrapper<>();
        Date[] dates = StatisticsDateUtil.getDateArray(statisticsQueryParam);
        queryWrapper.between(AfterSale::getCreateTime, dates[0], dates[1]);
        queryWrapper.eq(CharSequenceUtil.isNotEmpty(statisticsQueryParam.getStoreId()), AfterSale::getStoreId, statisticsQueryParam.getStoreId());

        return this.page(PageUtil.initPage(pageVO), queryWrapper);
    }

    /**
     * 创建售后
     *
     * @param afterSaleDTO 售后
     * @return 售后
     */
    private AfterSale addAfterSale(AfterSaleDTO afterSaleDTO) {
        //写入其他属性
        AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());

        AfterSale afterSale = new AfterSale();
        BeanUtil.copyProperties(afterSaleDTO, afterSale);

        //写入会员信息
        afterSale.setMemberId(authUser.getExtendId());
        afterSale.setMemberName(authUser.getNickName());

        //写入商家信息
        OrderItem orderItem = orderItemService.getBySn(afterSaleDTO.getOrderItemSn());
        Order order = orderService.getBySn(orderItem.getOrderSn());
        afterSale.setStoreId(order.getStoreId());
        afterSale.setStoreName(order.getStoreName());
        afterSale.setIsProxy(order.getIsProxy());
        afterSale.setSupplierId(order.getSupplierId());

        //写入订单商品信息
        afterSale.setGoodsImage(orderItem.getImage());
        afterSale.setGoodsName(orderItem.getGoodsName());
        afterSale.setSpecs(orderItem.getSpecs());
        afterSale.setFlowPrice(afterSaleDTO.getApplyRefundPrice());

        //写入交易流水号
        afterSale.setTradeSn(order.getTradeSn());
        afterSale.setOrderSn(order.getSn());
        afterSale.setPayOrderNo(order.getOutTradeNo());
        afterSale.setOrderItemSn(orderItem.getSn());

        //写入状态
        afterSale.setServiceStatus(AfterSaleStatusEnum.APPLY.name());

        //TODO 退还积分

        //创建售后单号
        afterSale.setSn(SnowFlake.createStr("A"));

        //是否包含图片
        if (afterSaleDTO.getImages() != null) {
            afterSale.setAfterSaleImage(afterSaleDTO.getImages());
        }

        //OrderFlow orderFlow = orderFlowService.getByOrderSn(order.getSn());
        if (afterSale.getNum().equals(orderItem.getNum())) {
            //计算退回金额
//            afterSale.setApplyRefundPrice(CurrencyUtil.sub(orderItem.getPriceDetailDTO().getFlowPrice(), orderItem.getPriceDetailDTO().getFreightPrice()));
            afterSale.setApplyRefundPrice(CurrencyUtil.sub((orderItem.getPriceDetailDTO().getFlowPrice() > 0 ? orderItem.getPriceDetailDTO().getFlowPrice() : orderItem.getFlowPrice()), orderItem.getPriceDetailDTO().getFreightPrice()));
            log.info("#addAfterSale# 计算退回金额 , afterSale.getApplyRefundPrice():{}", afterSale.getApplyRefundPrice());
            // 计算F分
            afterSale.setReturnFmoney(orderItem.getFmoney());
        } else {
            //单价计算
//            double utilPrice = CurrencyUtil.div(CurrencyUtil.sub(orderItem.getPriceDetailDTO().getFlowPrice(), orderItem.getPriceDetailDTO().getFreightPrice()), orderItem.getNum());
            double utilPrice = CurrencyUtil.div(CurrencyUtil.sub((orderItem.getPriceDetailDTO().getFlowPrice() > 0 ? orderItem.getPriceDetailDTO().getFlowPrice() : orderItem.getFlowPrice()), orderItem.getPriceDetailDTO().getFreightPrice()), orderItem.getNum());
            afterSale.setApplyRefundPrice(CurrencyUtil.mul(afterSale.getNum(), utilPrice));
            log.info("#addAfterSale# 单价计算 , afterSale.getApplyRefundPrice():{}", afterSale.getApplyRefundPrice());
            if (orderItem.getFmoney() > 0) {
                double singleFmoney = CurrencyUtil.div(orderItem.getFmoney(), orderItem.getNum());
                // 计算F分
                afterSale.setReturnFmoney(CurrencyUtil.mul(afterSale.getNum(), singleFmoney));
            }else {
                afterSale.setReturnFmoney(0D);
            }

        }

        Double applyRefundPrice = commission(orderItem, afterSale);
        afterSale.setApplyRefundPrice(applyRefundPrice);
        afterSale.setFlowPrice(applyRefundPrice);

        //添加售后
        this.save(afterSale);
        //发送售后消息
        this.sendAfterSaleMessage(afterSale);

        //根据售后状态。修改OrderItem订单中正在售后商品数量及状态
        this.updateOrderItemAfterSaleStatus(afterSale);

        //往供应链申请售后
        orderService.appOrderAfterSalesCreate(order,afterSale);

        return afterSale;
    }

    private Double commission(OrderItem orderItem, AfterSale afterSale) {
        Double refundPrice = afterSale.getApplyRefundPrice();
        // 获取退款商品
        Goods goods = goodsClient.getById(orderItem.getGoodsId());
        // 判断商品是不是门票
        if (null != goods && goods.getIsTicket()!=null && goods.getIsTicket()) {
            if (!Objects.equals(orderItem.getNum(), afterSale.getNum())) {
                throw new ServiceException("该商品只支持全额售后");
            }
            double commission = 0.5;

            LocalDate toDay = LocalDate.now();
            LocalDate endDate = LocalDate.of(2024, 1, 8);
            long daysBetween = ChronoUnit.DAYS.between(toDay, endDate);
            // 大于30天，退款50%， 小于30天，退款80%
            if (daysBetween <= 30) {
                commission = 0.8;
            }
            // 计算扣除金额
            double price = CurrencyUtil.mul(refundPrice, commission);
            log.info("#addAfterSale# #commission# , CurrencyUtil.mul(refundPrice, commission):{}", price);
            // 原退款金额 - 扣除金额 = 本次退款金额
            refundPrice = CurrencyUtil.sub(refundPrice, price);
            log.info("#addAfterSale# #commission# , CurrencyUtil.sub(refundPrice, price):{}", refundPrice);
        }
        return refundPrice;
    }

//    public void appAfterSalesCreate(Order order, OrderItem orderItem) {
//        GoodsSku goodsSku = goodsSkuClient.getGoodsSkuById(orderItem.getSkuId());
//        if (goodsSku != null && Integer.valueOf(1).equals(goodsSku.getThirdPartyPlatformType()) && StringUtils.isNotEmpty(orderItem.getOrderJsonVal())) {
//            AppAfterSalesCreate appAfterSalesCreate = new AppAfterSalesCreate();
//            appAfterSalesCreate.setOrder_item_id(Integer.valueOf(orderItem.getOrderItemIdVal()));
//            appAfterSalesCreate.setThird_order_sn(orderItem.getSn());
//            JSONObject jsonObject = orderService.appAfterSalesCreate(appAfterSalesCreate, order.getOrderStatus());
//            if (jsonObject.getInteger("code") != 0) {
//                log.error("申请售后失败=== {}" ,jsonObject.getString("msg"));
//                throw new ServiceException("申请售后失败");
//            }
//            Integer after_sales_id = jsonObject.getInteger("data");
//            order.setAfterSalesId(after_sales_id);
//            orderService.updateById(order);
//        }
//    }

    /**
     * 修改OrderItem订单中正在售后的商品数量及OrderItem订单状态
     *
     * @author ftyy
     */
    public void updateOrderItemAfterSaleStatus(AfterSale afterSale) {

        //根据商品skuId及订单sn获取子订单
        OrderItem orderItem =
                orderItemService.getOne(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn, afterSale.getOrderSn()).eq(OrderItem::getSkuId, afterSale.getSkuId()));
        AfterSaleStatusEnum afterSaleStatusEnum = AfterSaleStatusEnum.valueOf(afterSale.getServiceStatus());

        if (orderItem == null) {
            throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
        }

        switch (afterSaleStatusEnum) {
            //判断当前售后的状态---申请中
            case APPLY: {
                orderItem.setReturnNum(orderItem.getReturnNum() + afterSale.getNum());
                break;
            }

            //判断当前售后的状态---已拒绝,买家取消售后,卖家终止售后
            case REFUSE:
            case BUYER_CANCEL:
            case SELLER_TERMINATION: {
                orderItem.setReturnNum(orderItem.getReturnNum() - afterSale.getNum());
                break;
            }
            default:
                break;
        }
        //修改orderItem订单
        this.updateOrderItem(orderItem);
    }


    /**
     * 检查当前订单状态是否为可申请当前售后类型的状态
     *
     * @param afterSaleDTO 售后
     */
    private void checkAfterSaleType(AfterSaleDTO afterSaleDTO) {

        //判断数据是否为空
        if (null == afterSaleDTO || CharSequenceUtil.isEmpty(afterSaleDTO.getOrderItemSn())) {
            throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
        }

        //获取订单货物判断是否可申请售后
        OrderItem orderItem = orderItemService.getBySn(afterSaleDTO.getOrderItemSn());

        //未申请售后或部分售后订单货物才能进行申请
        if (!orderItem.getAfterSaleStatus().equals(OrderItemAfterSaleStatusEnum.NOT_APPLIED.name()) && !orderItem.getAfterSaleStatus().equals(OrderItemAfterSaleStatusEnum.PART_AFTER_SALE.name())) {
            throw new ServiceException(ResultCode.AFTER_SALES_BAN);
        }

        //申请商品数量不能超过商品总数量-售后商品数量
        int canReturnNum = orderItem.getReturnNum() != null ? orderItem.getNum() - orderItem.getReturnNum() : orderItem.getNum();
        if (afterSaleDTO.getNum() > canReturnNum) {
            throw new ServiceException(ResultCode.AFTER_GOODS_NUMBER_ERROR);
        }


        //获取售后类型
        Order order = orderService.getBySn(orderItem.getOrderSn());
        AfterSaleTypeEnum afterSaleTypeEnum = AfterSaleTypeEnum.valueOf(afterSaleDTO.getServiceType());
        switch (afterSaleTypeEnum) {
            case RETURN_MONEY -> {
                //只处理已付款的售后
                if (!PayStatusEnum.PAID.name().equals(order.getPayStatus())) {
                    throw new ServiceException(ResultCode.AFTER_SALES_BAN);
                }
                this.checkAfterSaleReturnMoneyParam(afterSaleDTO);
            }
            case RETURN_GOODS -> {
                //是否为有效状态
                boolean availableStatus = CharSequenceUtil.equalsAny(order.getOrderStatus(), OrderStatusEnum.DELIVERED.name(),
                        OrderStatusEnum.COMPLETED.name());
                if (!PayStatusEnum.PAID.name().equals(order.getPayStatus()) && availableStatus) {
                    throw new ServiceException(ResultCode.AFTER_SALES_BAN);
                }
            }
        }

    }

    /**
     * 检测售后-退款参数
     *
     * @param afterSaleDTO 售后DTO
     */
    private void checkAfterSaleReturnMoneyParam(AfterSaleDTO afterSaleDTO) {
        //如果为线下支付银行信息不能为空
        if (AfterSaleRefundWayEnum.OFFLINE.name().equals(afterSaleDTO.getRefundWay())) {
            boolean emptyBankParam =
                    CharSequenceUtil.isEmpty(afterSaleDTO.getBankDepositName()) || CharSequenceUtil.isEmpty(afterSaleDTO.getBankAccountName()) || CharSequenceUtil.isEmpty(afterSaleDTO.getBankAccountNumber());
            if (emptyBankParam) {
                throw new ServiceException(ResultCode.RETURN_MONEY_OFFLINE_BANK_ERROR);
            }

        }
    }

    /**
     * 根据sn获取信息
     *
     * @param sn 订单sn
     * @return 售后信息
     */
    private AfterSale getBySn(String sn) {
        QueryWrapper<AfterSale> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sn", sn);
        if (UserContext.getCurrentUser() != null) {
            switch (Objects.requireNonNull(UserContext.getCurrentUser()).getScene()) {
                case MEMBER -> queryWrapper.eq("member_id", UserContext.getCurrentUser().getExtendId());
                case SUPPLIER -> queryWrapper.nested(n -> n.eq("supplier_id", UserContext.getCurrentUser().getExtendId()).or().eq("store_id",
                        UserContext.getCurrentUser().getExtendId()));
                case STORE -> queryWrapper.nested(n -> n.eq("store_id", UserContext.getCurrentUser().getExtendId()).or().eq("member_id",
                        UserContext.getCurrentUser().getExtendId()));
                default -> {
                }
            }
        }
        return this.getOne(queryWrapper);
    }

    /**
     * 根据售后编号修改售后单
     *
     * @param afterSaleSn 售后单号
     * @param afterSale   售后单
     */
    private void updateAfterSale(String afterSaleSn, AfterSale afterSale) {
        //修改售后单状态
        LambdaUpdateWrapper<AfterSale> queryWrapper = Wrappers.lambdaUpdate();
        queryWrapper.eq(AfterSale::getSn, afterSaleSn);
        this.update(afterSale, queryWrapper);
    }

    /**
     * 发送售后消息
     *
     * @param afterSale 售后对象
     */
    public void sendAfterSaleMessage(AfterSale afterSale) {
        amqpSender.send(AmqpMessage.builder().exchange(amqpExchangeProperties.getAfterSale()).routingKey(AfterSaleRoutingKey.AFTER_SALE_STATUS_CHANGE).message(afterSale).build());
    }

    /**
     * 功能描述: 获取售后商品数量及已完成售后商品数量修改orderItem订单
     *
     * @param orderItem,afterSaleList
     * @author ftyy
     **/
    private void updateOrderItemGoodsNumber(OrderItem orderItem, List<AfterSale> afterSaleList) {
        //根据售后状态获取不是已结束的售后记录
        List<AfterSale> implementList =
                afterSaleList.stream().filter(afterSale -> afterSale.getServiceStatus().equals(AfterSaleStatusEnum.APPLY.name()) || afterSale.getServiceStatus().equals(AfterSaleStatusEnum.PASS.name()) || afterSale.getServiceStatus().equals(AfterSaleStatusEnum.BUYER_RETURN.name()) || afterSale.getServiceStatus().equals(AfterSaleStatusEnum.SELLER_CONFIRM.name()) || afterSale.getServiceStatus().equals(AfterSaleStatusEnum.WAIT_REFUND.name()) || afterSale.getServiceStatus().equals(AfterSaleStatusEnum.COMPLETE.name())).collect(Collectors.toList());

        if (!implementList.isEmpty()) {
            //遍历售后记录获取售后商品数量
            implementList.forEach(a -> orderItem.setReturnNum(orderItem.getReturnNum() + a.getNum()));
        }

        //获取已完成售后订单数量
        List<AfterSale> completeList =
                afterSaleList.stream().filter(afterSale -> afterSale.getServiceStatus().equals(AfterSaleStatusEnum.COMPLETE.name())).collect(Collectors.toList());

        if (!completeList.isEmpty()) {
            //遍历售后记录获取已完成售后商品数量
            completeList.forEach(a -> orderItem.setReturnNum(orderItem.getReturnNum() + a.getNum()));
        }
    }

    /**
     * 功能描述:  修改orderItem订单
     *
     * @param orderItem
     * @return void
     * @author ftyy
     **/
    private void updateOrderItem(OrderItem orderItem) {
        //订单状态不能为新订单,已失效订单或未申请订单才可以去修改订单信息
        OrderItemAfterSaleStatusEnum afterSaleTypeEnum = OrderItemAfterSaleStatusEnum.valueOf(orderItem.getAfterSaleStatus());
        switch (afterSaleTypeEnum) {
            //售后状态为：未申请 部分售后 已申请
            case NOT_APPLIED, PART_AFTER_SALE, ALREADY_APPLIED -> {
                //通过正在售后商品总数修改订单售后状态
                if (orderItem.getReturnNum().equals(orderItem.getNum())) {
                    //修改订单的售后状态--已申请
                    orderItem.setAfterSaleStatus(OrderItemAfterSaleStatusEnum.ALREADY_APPLIED.name());
                } else if (orderItem.getReturnNum().equals(0)) {
                    //修改订单的售后状态--未申请
                    orderItem.setAfterSaleStatus(OrderItemAfterSaleStatusEnum.NOT_APPLIED.name());
                } else {
                    //修改订单的售后状态--部分售后
                    orderItem.setAfterSaleStatus(OrderItemAfterSaleStatusEnum.PART_AFTER_SALE.name());
                }
            }
            default -> {
            }
        }
        orderItemService.update(new LambdaUpdateWrapper<OrderItem>().eq(OrderItem::getSn, orderItem.getSn()).set(OrderItem::getAfterSaleStatus,
                orderItem.getAfterSaleStatus()).set(OrderItem::getReturnNum, orderItem.getReturnNum()));
    }

}